home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / PeerAware 1.03 / PeerAware-Setup.exe / Html / scripts / richdraw.js < prev    next >
Text File  |  2008-09-07  |  68KB  |  2,302 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  
  3. This code has been relicensed under LGPL as permitted by original license.
  4.  
  5. Copyright Cumulate Draw Editor
  6.  
  7. This library is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU Lesser General Public
  9. License as published by the Free Software Foundation; either
  10. version 2.1 of the License, or (at your option) any later version.
  11.  
  12. This library is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. Lesser General Public License for more details.
  16.  
  17. You should have received a copy of the GNU Lesser General Public
  18. License along with this library; if not, write to the Free Software
  19. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 
  20.  * ***** END LICENSE BLOCK ***** */
  21.  
  22. /**
  23. *RichDrawEditor: the idea is to provide an abstract editor interface which
  24. *manipulates vml or svg renderers,
  25. *
  26. *constructor, set up initial values for state variables and add listeners
  27. **/
  28.  
  29.  
  30. function RichDrawEditor(elem, renderer) {
  31.   gApplication = new Application();
  32.   this.initialized=false;
  33.   this.iUser='';
  34.   this.container = elem;
  35.   this.page=$("_page");
  36.   this.width=700;
  37.   this.height=700;
  38.   this.DEFAULT_PAGE_WIDTH=700;
  39.   this.DEFAULT_PAGE_HEIGHT=700;
  40.   this.MAX_WIDTH=2000;
  41.   this.MAX_HEIGHT=2000;
  42.   this.gridX = 1;
  43.   this.gridY = 1;
  44.   this.mouseDownX = 0;
  45.   this.mouseDownY = 0;
  46.   this.prevZoom=1.0;
  47.   this.zoom=1.0;
  48.   this.prevWidth=0;
  49.   this.prevHeight=0;
  50.   this.prevLeft=0;
  51.   this.prevTop=0;
  52.   this.prevRotation=0;
  53.   this.prevMode='';
  54.   this.mode = 'select';
  55.   this.resizeMode='';//possible values are left-stretch, right-stretch,top-stretch,bottom-stretch
  56.   this.fillColor = '';
  57.   this.lineColor = '';
  58.   this.lineWidth = '';
  59.   this.lineStyle='none';
  60.   this.opacity='1.0';
  61.   this.gradient='solid';
  62.   this.linedashstyle='solid';
  63.   this.shadowOn="false";
  64.   this.shiftMode=false;
  65.   this.selected = null;
  66.   //the current shape which is under line draw!!!
  67.   this.lineActiveShape=null;
  68.   this.dragStarted=false;
  69.   this.textEditMode=false;
  70.   this.textToolBeginNew=true;
  71.   this.resizeCounter=0;
  72.   this.dragCounter=0;
  73.   var font=new Object();
  74.   font.size='';
  75.   font.family='';
  76.   font.color='';
  77.   font.align='';
  78.   font.italics='';
  79.   font.bold='';
  80.   this.fillUpFont(font);
  81.   this.font=font;
  82.   this.shapeProps=new Array();
  83.   this.shapeProps["table"]=$("_shapeTable");
  84.   this.shapeProps["x"]=$("_x");
  85.   this.shapeProps["y"]=$("_y");
  86.   this.shapeProps["width"]=$("_width");
  87.   this.shapeProps["height"]=$("_height");
  88.   this.shapeProps["rotation"]=$("_rotation");
  89.   this.lineProps=new Array();
  90.   this.lineProps["table"]=$("_connectorTable");
  91.   this.lineProps["x1"]=$("_x1");
  92.   this.lineProps["x2"]=$("_x2");
  93.   this.lineProps["y1"]=$("_y1");
  94.   this.lineProps["y2"]=$("_y2");
  95.   this.lineProps["type"]=$("_lineType");
  96.   this.pageProps=new Array();
  97.   this.pageProps["table"]=$("_pageTable");
  98.   this.pageProps["x"]=$("_pageX");
  99.   this.pageProps["y"]=$("_pageY");
  100.   this.pageProps["width"]=$("_pageWidth");
  101.   this.pageProps["height"]=$("_pageHeight");
  102.   //one day we will allow multiple objects in the clipboard
  103.   this.clipboard=null;
  104.   this.selectedBounds = { x:0, y:0, width:0, height: 0 };
  105.  
  106.   this.onselect = function() {}
  107.   this.onunselect = function() {}
  108.   //initialize the renderer
  109.   this.renderer = renderer;
  110.   this.renderer.init(this.container);
  111.  
  112.   this.onMouseDownListener = this.onMouseDown.bindAsEventListener(this);
  113.   this.onMouseUpListener = this.onMouseUp.bindAsEventListener(this);
  114.   this.onDragListener = this.onDrag.bindAsEventListener(this);
  115.   this.onDrawListener = this.onDraw.bindAsEventListener(this);
  116.  
  117.   this.onHitListener = this.onHit.bindAsEventListener(this);
  118.  
  119.  
  120.   this.onSelectStartListener = this.onSelectStart.bindAsEventListener(this);
  121.   this.onMouseOverListener=this.onMouseOver.bindAsEventListener(this);
  122.   this.onMouseOutListener=this.onMouseOut.bindAsEventListener(this);
  123.   this.onShapeMouseOutListener=this.onShapeMouseOut.bindAsEventListener(this);
  124.   this.onShapeMouseEnterListener=this.onShapeMouseEnter.bindAsEventListener(this);
  125.   this.onKeyPressListener=this.onKeyPress.bindAsEventListener(this);
  126.   this.onKeyUpListener=this.onKeyUp.bindAsEventListener(this);
  127.   this.onDblClickListener=this.onDblClick.bindAsEventListener(this);
  128.   this.onTextEditEndListener=this.onTextEditEnd.bindAsEventListener(this);
  129.   Event.observe(this.container, "mousedown", this.onMouseDownListener);
  130.   Event.observe(this.container, "mouseup", this.onMouseUpListener);
  131.   Event.observe(this.container,"mouseout",this.onMouseOutListener);
  132.   Event.observe(this.container, "selectstart", this.onSelectStartListener);  
  133.   Event.observe(this.container.ownerDocument,'keypress',this.onKeyPressListener);
  134.   Event.observe(this.container.ownerDocument,'keyup',this.onKeyUpListener);
  135. }
  136.  
  137. /**
  138. *setup initial values for the font
  139. **/
  140. RichDrawEditor.prototype.fillUpFont=function(font){
  141.         if(font.size=='')
  142.             font.size=16;
  143.         if(font.family=='')
  144.             font.family="'arial'";
  145.         if(font.italics=='')
  146.             font.italics="normal";
  147.         if(font.bold=='')
  148.             font.bold="normal"
  149.         if(font.align=='')
  150.             font.align="center";
  151.         if(font.color=='')
  152.             font.color="black";
  153.             
  154.  
  155. }
  156.  
  157. /**
  158. *Initialized the workspace
  159. **/
  160. RichDrawEditor.prototype.initializationDone = function() {
  161.     this.initialized=true;
  162. };
  163.  
  164.  
  165. /**
  166. *clear the workspace
  167. **/
  168. RichDrawEditor.prototype.clearWorkspace = function() {
  169.     this.container.innerHTML = '';
  170.     
  171. };
  172. /******************************begin cut/copy/paste/delete operations***********************************/
  173. /**
  174. *delete the selection and remove the trackers
  175. **/
  176. RichDrawEditor.prototype.deleteSelection = function() {
  177.   
  178.   if (this.selected) {
  179.     //remove all tracker components!!
  180.     if($('tracker-group')){
  181.     
  182.      Event.stopObserving($('tracker-group'),"mouseover",this.onMouseOverListener);
  183.     }
  184.      Event.stopObserving(this.selected,"dblclick",this.onDblClickListener);
  185.     this.renderer.remove(this.container.ownerDocument.getElementById('tracker-group'));
  186.     this.renderer.remove(this.selected);
  187.     this.selected = null;
  188.     //this.updateShapeInfo(null);
  189.   }
  190.   else{
  191.     setHelp("Select a shape to delete");
  192.   }
  193. };
  194.  
  195. /**
  196. *copy and then delete the selection
  197. **/
  198. RichDrawEditor.prototype.cut=function(){
  199.     if(this.selected){
  200.         this.copy();
  201.         this.deleteSelection();    
  202.         this.unselect();
  203.     }
  204.     else{
  205.         setHelp("Nothing to cut,Please select a shape first");
  206.     }
  207. };
  208.  
  209. /**
  210. *Save to the clipboard
  211. */
  212.  
  213. RichDrawEditor.prototype.copyToRemote=function(){
  214.     if(this.selected){
  215.         return this.renderer.copy(this.selected);
  216.     }
  217.     return null;
  218. };
  219.  
  220. RichDrawEditor.prototype.copy=function(){
  221.     if(this.selected){
  222.         //I know this is weird but clone node does not seem to work,so we copy the outer html
  223.         this.clipboard=this.renderer.copy(this.selected);
  224.     }
  225.     else{
  226.         setHelp("Nothing to copy,Please select a shape first");
  227.     }
  228. };
  229.  
  230. /**
  231. *paste function
  232. *wierd IE bug which forces us to set zindex of lines to 0 until they are added
  233. *nodeArray[i].getElementsByTagName("line")[0].style.zIndex=0;
  234. *another wierdness is that polyline.points.value does not correspond to polyline.points.item(x).value, so we
  235. * first set the points to 0,0, then add them to the container and then set the orignal points which we preserved
  236. * during copy, where we called savePolyLinePath
  237. **/
  238. RichDrawEditor.prototype.paste=function(){
  239.     
  240.     if(this.clipboard!=null){
  241.         var node=this.renderer.paste(this.clipboard);
  242.         //add listener to added child
  243.         this.addNewShapeListeners(node);
  244.         this.clipboard=this.renderer.copy(node);
  245.         return node;
  246.     }
  247.     else{
  248.         setHelp("Nothing to paste,Use copy or cut on selected shape");
  249.     }
  250.  
  251. }
  252.  
  253. /**
  254. * a utility function to add all the required listener after a new shape has been 
  255. * added
  256. **/
  257. RichDrawEditor.prototype.addNewShapeListeners=function(shape){
  258.     if(!shape)return;
  259.     Event.observe(shape, "mousedown", this.onHitListener); 
  260.     
  261.     Event.observe(shape,"mouseover",this.onShapeMouseEnterListener);
  262.     Event.observe(shape,"mouseout",this.onShapeMouseOutListener);
  263. }
  264.  
  265.  
  266. /****END DELETE, CUT,COPY,PASTE functions*****************/
  267. /****************BRING TO FRONT/BACK FUNCTIONS*************************/
  268. /**
  269. *bring to front,the listeners are refreshed since in SVG there is no real z-index operation, so 
  270. *we remove and readd!
  271. *@param shape
  272. **/
  273. RichDrawEditor.prototype.bringToFront=function(shape){
  274.     var subject=(shape)?shape:this.selected;
  275.     subject=this.renderer.bringToFront(subject);
  276.     if(subject){
  277.         this.addNewShapeListeners(subject);
  278.         this.select(subject);
  279.     }
  280. }
  281. /**
  282. *send to back, the listeners are refreshed since in SVG there is no real z-index operation, so 
  283. *we remove and readd!. 
  284. *@param shape
  285. **/
  286. RichDrawEditor.prototype.sendToBack=function(shape){
  287.  
  288.     var subject=(shape)?shape:this.selected;
  289.     var subject=this.renderer.sendToBack(subject);
  290.     if(subject){
  291.         this.addNewShapeListeners(subject);
  292.         this.select(subject);
  293.     }
  294. }
  295. /*********************END BRING TO FRONT/BACK FUNCTIONS**********************/
  296.  
  297. /**
  298. * select and show tracker
  299. **/
  300. RichDrawEditor.prototype.select = function(elem) {
  301.   if (elem == this.selected)
  302.     return;
  303.  
  304.   this.selected = elem;
  305.   var tracker=this.renderer.showTracker(this.selected);
  306.   Event.observe(tracker,"mouseover",this.onMouseOverListener);
  307.   // if(!this.renderer.isConnector(this.selected)){
  308.     Event.observe(this.selected,"dblclick",this.onDblClickListener);
  309.   //}
  310.   setHelp("To move the shape, drag it. To resize, use resize boxes.<b>To Set Text, double click</b>"); 
  311.   this.onselect(this);
  312.   this.updateShapeInfo(this.selected);
  313. };
  314.  
  315. /**
  316. *unselect and remove tracker, 
  317. *if text is being edited, end that operation.
  318. **/
  319. RichDrawEditor.prototype.unselect = function() {
  320.     
  321.   if (this.selected!=null) {
  322.     if(this.textEditMode){
  323.         this.finishTextEdit();
  324.         this.textEditMode=false;
  325.     }
  326.     if(this.mode!="text"){
  327.         this.textModeBeginNew=false;
  328.     }
  329.     Event.stopObserving(this.selected,"dblclick",this.onDblClickListener);
  330.     this.selected = null;
  331.     this.onunselect(this);
  332.     Event.stopObserving(this.container,"mouseover",this.onMouseOverListener);
  333.     
  334.     this.updateShapeInfo(null);
  335.     if(this.container.ownerDocument.getElementById('tracker-group')!=null){
  336.         this.renderer.remove(this.container.ownerDocument.getElementById('tracker-group'));
  337.         
  338.         
  339.     }
  340.     
  341.     var activeShapeTracker=$("active-shape-tracker");
  342.     if(activeShapeTracker)
  343.         this.renderer.remove(activeShapeTracker);
  344.   }
  345.       var lineTracker=$("line-tracker");
  346.       if(lineTracker){
  347.           this.renderer.remove(lineTracker);
  348.       }
  349. }
  350. /***************************************TEXT related functions************************/
  351. /**
  352. *this is called when a shape is double clicked, 
  353. *it displays the text box for the selected shape 
  354. **/
  355. RichDrawEditor.prototype.onDblClick=function(event){
  356.     if(!this.selected){
  357.         return false;
  358.     }
  359.     
  360.     else{
  361.         this.startTextEdit(this.selected);
  362.     }
  363. }
  364.  
  365. /**
  366. *start the text editing
  367. *@param {shape} the shape
  368. **/
  369. RichDrawEditor.prototype.startTextEdit=function(shape){
  370.  
  371.     setHelp("Enter your text and then click anywhere outside the text area");
  372.     var text=$('__shapeText');
  373.     var textString=this.renderer.getShapeText(shape);
  374.     if(textString){
  375.         text.value=textString;
  376.     }
  377.     else{
  378.         text.value="";
  379.     }
  380.     text.style.visibility="visible";
  381.     var bounds=this.renderer.getTextBounds(shape,"",this.zoom);
  382.     text.style.marginLeft=bounds.x>3?(bounds.x-3):0;
  383.     text.style.marginTop=bounds.y>3?(bounds.y-3):0;
  384.     if(bounds.width>=35){
  385.         text.style.width=parseInt(bounds.width)+6;
  386.     }
  387.     else{
  388.         text.style.width=35;
  389.     }
  390.     if(bounds.height>=35){
  391.         text.style.height=parseInt(bounds.height)+6;
  392.     }
  393.     else{
  394.         text.style.height=35;
  395.     }
  396.     
  397.     this.setTextAreaFont(text);
  398.     
  399.     this.renderer.remove(text);
  400.     this.container.appendChild(text);
  401.     text.focus();
  402.     text.style.zIndex=this.renderer.maxIndex;
  403.      Event.stopObserving(this.container, "mousedown", this.onMouseDownListener);
  404.     Event.stopObserving(this.container, "mouseup", this.onMouseUpListener);
  405.     Event.stopObserving(this.container, "selectstart", this.onSelectStartListener);  
  406.     Event.stopObserving(this.container,'keypress',this.onKeyPressListener);
  407.     Event.stopObserving(this.container,'keyup',this.onKeyUpListener);
  408.     Event.stopObserving(this.container, "mousemove", this.onDragListener);  
  409.     Event.observe(this.container,'mousedown',this.onTextEditEndListener);
  410.     setTimeout("c.manageTextSize()",100);
  411.     this.textEditMode=true;
  412. }
  413. /**
  414.  * manage the size of the text area based on size of the text being entered
  415.  */
  416. RichDrawEditor.prototype.manageTextSize=function(){
  417.     if(!this.selected||(!this.renderer.isConnector(this.selected)&&(!this.selected.getElementsByTagName("text-bound")>0)))return;
  418.     var text=$('__shapeText');
  419.     if(!text.style.visibility=="visible")return;
  420.     var bounds=this.renderer.getTextBounds(this.selected,text.value,this.zoom);
  421.     text.style.marginLeft=bounds.x>3?(bounds.x-3):0;
  422.     text.style.marginTop=bounds.y>3?(bounds.y-3):0;
  423.     if(bounds.width>=35){
  424.         text.style.width=parseInt(bounds.width)+6;
  425.     }
  426.     else{
  427.         text.style.width=35;
  428.     }
  429.     if(bounds.height>=35){
  430.         text.style.height=parseInt(bounds.height)+6;
  431.     }
  432.     else{
  433.         text.style.height=35;
  434.     }
  435.     setTimeout("c.manageTextSize()",100);
  436. }
  437. /**
  438. *basically set the font of the test area based on either 
  439. *the currently selected shape's font properties or the default
  440. *if the current shape is empty
  441. **/
  442. RichDrawEditor.prototype.setTextAreaFont=function(text){
  443.     var shapeFont=this.renderer.getFont(this.selected);
  444.         if(shapeFont.size!=''){
  445.             text.style.fontSize=(shapeFont.size*this.zoom);
  446.         }
  447.         else{
  448.             text.style.fontSize=(this.font.size*this.zoom);
  449.         }
  450.         
  451.         if(shapeFont.color!=''){
  452.             text.style.strokecolor=shapeFont.color;
  453.             text.style.color=shapeFont.color;
  454.         }
  455.         else{
  456.             text.style.strokecolor=this.font.color;
  457.             text.style.color=this.font.color;
  458.         }
  459.         if(shapeFont.family!=''){
  460.             text.style.fontFamily=shapeFont.family;
  461.         
  462.         }
  463.         else{
  464.             text.style.fontFamily=this.font.family;
  465.         }
  466.         if(shapeFont.bold!=''){
  467.             
  468.             text.style.fontWeight=shapeFont.bold;
  469.         }
  470.         else{
  471.             text.style.fontWeight=this.font.bold;
  472.         }
  473.         if(shapeFont.italics!=''){
  474.             text.style.fontStyle=shapeFont.italics;
  475.         }
  476.         else{
  477.             text.style.fontStyle=this.font.italics;
  478.         }
  479.  
  480. }
  481. /**
  482. *called when user clicks an area other than the active text area, 
  483. *signals end of text editing, time to set the text in the shape
  484. **/
  485. RichDrawEditor.prototype.onTextEditEnd=function(event){
  486.     if(!this.selected||!this.textEditMode||!event){
  487.         return;
  488.     }
  489.     else{
  490.         
  491.         var source=Event.element(event);
  492.         if(event&&source&&source.id=="__shapeText"){
  493.             return;
  494.         }
  495.         this.finishTextEdit();
  496.         this.unselect();
  497.     }
  498.  
  499.  
  500. };
  501. /**
  502. *this method should be called when we want to force the text edit operation to end
  503. **/
  504. RichDrawEditor.prototype.finishTextEdit=function(){
  505.         setHelp("Finished editing text");
  506.         var shapeText=$('__shapeText');
  507.         var text=shapeText.value;
  508.         if(!text||text.length==0)text=" ";
  509.         this.clearShapeText();
  510.         var shapeFont=this.renderer.getFont(this.selected);
  511.         this.renderer.setShapeText(this.selected,text,this.font,false,shapeFont,this.zoom);
  512.     if(this.mode=="text"&&!this.textToolBeginNew)
  513.     {
  514.         var transmitData = this.copyToRemote();
  515.         if (transmitData != null)
  516.             gApplication.transmit('w', "cpy " + transmitData);
  517.     }
  518.     else
  519.         gApplication.transmit('w', 'cmd txt txt ' + this.selected.id + ' ' + text);
  520.         
  521.         if(!this.renderer.isConnector(this.selected)){
  522.             this.resetTextForAttachedConnectors(this.selected);
  523.         }
  524.         shapeText.style.visibility="hidden";
  525.         this.textEditMode=false;
  526.         Event.observe(this.container, "mousedown", this.onMouseDownListener);
  527.         Event.observe(this.container, "mouseup", this.onMouseUpListener);
  528.         Event.observe(this.container, "selectstart", this.onSelectStartListener);  
  529.         Event.observe(this.container,'keypress',this.onKeyPressListener);
  530.         Event.observe(this.container,'keyup',this.onKeyUpListener);
  531.         Event.stopObserving(this.container,"mousedown",this.onTextEditEndListener);
  532.  
  533. }
  534.  
  535. /**
  536. *clear the shape text, this removes the shape text and stores it in a temporary location, we do this for performance
  537. * reasons, since we don't want to draw every single shape line every time we move.
  538. * @param shape--optional, if no shape provided, this.selected will be used
  539. **/
  540.  
  541. RichDrawEditor.prototype.clearShapeText=function(shape){
  542.     var subject=shape;
  543.     if(!subject){
  544.         subject=this.selected;    
  545.     }
  546.     if(subject){
  547.                 this.renderer.getShapeText(subject);
  548.                 this.renderer.getFont(subject);
  549.                 this.renderer.clearShapeText(subject);
  550.                 if(!this.renderer.isConnector(subject)){
  551.                     this.clearTextForAttachedConnectors(subject);
  552.                     }
  553.                 }
  554.         
  555. }
  556. /**
  557. *reset the shape text after the shape move is complete
  558. *@param shape--optional, if no shape provided, this.selected will be used
  559. */
  560. RichDrawEditor.prototype.resetShapeText=function(shape){
  561.     
  562.     var subject=shape;
  563.     if(!subject){
  564.         subject=this.selected;    
  565.     }
  566.     if(subject){
  567.             
  568.              var text=this.renderer.getShapeText(subject);
  569.              var shapeFont=this.renderer.getFont(subject);
  570.              if(text){
  571.                   this.renderer.setShapeText(subject,text,this.font,false,shapeFont,this.zoom);
  572.              }
  573.              if(!this.renderer.isConnector(subject)){
  574.                     this.resetTextForAttachedConnectors(subject);
  575.                 }
  576.             }
  577. }
  578. /**
  579.  * clear the text for all the connectors attached to a particular shape
  580.  * @param shape--optional, if no shape provided, this.selected will be used
  581.  */
  582.  RichDrawEditor.prototype.clearTextForAttachedConnectors=function(shape){
  583.      var subject=shape;
  584.      if(!subject)
  585.          subject=this.selected;
  586.      var connList=this.renderer.getAllConnectorsForShape(subject);
  587.      for(var i=0;i<connList.length;i++){
  588.          if(connList[i]){
  589.              this.clearShapeText(connList[i]);
  590.          }
  591.      }
  592.  }
  593.  /**
  594.  * reset the text for all the connectors attached to a particular shape
  595.  * @param shape--optional, if no shape provided, this.selected will be used
  596.  */
  597.  RichDrawEditor.prototype.resetTextForAttachedConnectors=function(shape){
  598.      var subject=shape;
  599.      if(!subject)
  600.          subject=this.selected;
  601.      var connList=this.renderer.getAllConnectorsForShape(shape);
  602.      for(var i=0;i<connList.length;i++){
  603.          if(connList[i]){
  604.              this.resetShapeText(connList[i]);
  605.          }
  606.      }
  607.  }
  608. /****************************END TEXT functions************************************/
  609.  
  610.  
  611. /**
  612. *getSeletedElement
  613. **/
  614. RichDrawEditor.prototype.getSelectedElement = function() {
  615.   return this.selected;
  616. };
  617.  
  618. /**
  619. *set grid
  620. **/
  621. RichDrawEditor.prototype.setGrid = function(horizontal, vertical) {
  622.   this.gridX = horizontal;
  623.   this.gridY = vertical;
  624. };
  625.  
  626. /** 
  627. *during open, we first reset zoom to 1, add the shapes and then set it back to "zoom-factor"
  628. **/
  629. RichDrawEditor.prototype.open=function(div){
  630.     
  631.         this.removeAll();
  632.         //reset the zoom to 1
  633.         this.setZoom((1.0/this.zoom));
  634.         //now call the renderer specific operations for open
  635.         this.renderer.open(div);
  636.         //get all shapes
  637.         var nodes=this.renderer.getAllShapes(this.container.ownerDocument);
  638.         var nodeArray=$A(nodes);
  639.         //get all connectors
  640.         nodes=this.renderer.getAllConnectors(this.container.ownerDocument);
  641.         for(var i=0;i<nodes.length;i++){
  642.             nodeArray[nodeArray.length]=nodes[i];
  643.         }
  644.         for(var i=0;i<nodeArray.length;i++){
  645.             var node=nodeArray[i];
  646.             this.addNewShapeListeners(node);
  647.         }
  648.         
  649.         //first set the pageSize as derived from the file being opened
  650.         var pageSize=div.getElementsByTagName("page-size");
  651.         var width=this.DEFAULT_PAGE_WIDTH;
  652.         var hieght=this.DEFAULT_PAGE_HEIGHT;
  653.         if(pageSize&&pageSize.length>0){
  654.             width=pageSize.item(0).getAttribute("width");
  655.             hieght=pageSize.item(0).getAttribute("height");
  656.             
  657.         }
  658.         this.setPageSize(width,hieght);
  659.         //now set the zoom
  660.         var zoomElement=div.getElementsByTagName("zoom-factor");
  661.         var factor=0.8;
  662.         if(zoomElement&&zoomElement.length>0){
  663.             factor=zoomElement.item(0).getAttribute("factor");
  664.             
  665.         }
  666.         this.setZoom(factor);
  667.         $('_zoomValue').innerHTML=(this.getZoom()*100).toFixed(0)+"%";
  668. };
  669.  
  670. /** 
  671. *used by new function to reset the editor to defaults in prepration for new
  672. */
  673. RichDrawEditor.prototype.reset=function(){
  674.  
  675.     gApplication.transmit('w', 'cmd reset');
  676.  
  677.     this.removeAll();
  678.     this.setPageSize(this.DEFAULT_PAGE_WIDTH,this.DEFAULT_PAGE_HEIGHT);
  679. }
  680.  
  681. /**
  682. *used by "new" toolbar function, clear the canvas
  683. **/
  684. RichDrawEditor.prototype.removeAll=function(){
  685.         this.unselect();
  686.         var nodes=this.renderer.getAllShapes(this.container.ownerDocument);
  687.         
  688.         var nodeArray=$A(nodes);
  689.         nodes=this.renderer.getAllConnectors(this.container.ownerDocument);
  690.         for(var i=0;i<nodes.length;i++){
  691.             nodeArray[nodeArray.length]=nodes[i];
  692.         }
  693.         for(var i=0;i<nodeArray.length;i++){
  694.             var node=nodeArray[i];
  695.             this.renderer.remove(node);
  696.         }
  697.  
  698. }
  699. /**
  700. *set the current edit mode
  701. **/
  702. RichDrawEditor.prototype.setMode=function (value){
  703.     this.mode=value;
  704.     if(value=='line'){
  705.         this.renderer.setCursor(this.container,"./cursors/line-draw.cur");
  706.     }
  707.     else if(value=='ortho-line'){
  708.         this.renderer.setCursor(this.container,"./cursors/orth-draw.cur");
  709.     }
  710.     else if(value=='curve-line'){
  711.         this.renderer.setCursor(this.container,"./cursors/curve-draw.cur");
  712.     }
  713.     else if (value=='text'){
  714.         this.renderer.setCursor(this.container,"./cursors/text.cur");
  715.     }
  716.     else{
  717.         this.renderer.setCursor(this.container,"default");
  718.     }
  719.  
  720. }
  721. /**
  722. *this is the driver for all toolbar related commands,
  723. *if a shape is selected the command is delegated to the renderer
  724. *otherwise it is handled by the editor itself
  725. **/
  726. RichDrawEditor.prototype.editCommand = function(cmd, value)
  727. {
  728.     this.externaleditCommand(cmd, value, false);
  729. }
  730. RichDrawEditor.prototype.externaleditCommand = function(cmd, value, external)
  731. {
  732.     if (!external && this.initialized)
  733.     {
  734.         if (!this.selected)
  735.             gApplication.transmit('w', 'cmd ' + cmd + " " + value);
  736.         else
  737.             gApplication.transmit('w', 'cmd ' + cmd + " " + value + " " + this.selected.id);
  738.     }
  739.   //debugger;
  740.   if (cmd == 'mode') {
  741.     this.setMode(value);
  742.   }
  743.   if(cmd=='zoom'){
  744.     this.setZoom(value);
  745.   }
  746.   else if (this.selected == null) {
  747.     if (cmd == 'fillcolor') {
  748.       this.fillColor = value;
  749.     }
  750.     else if (cmd == 'linecolor') {
  751.       this.lineColor = value;
  752.     }
  753.     else if (cmd == 'linewidth') {
  754.       this.lineWidth = parseInt(value) + 'px';
  755.     }
  756.     else if (cmd=='opacity'){
  757.       this.opacity=value;
  758.     }
  759.      else if (cmd=='gradient'){
  760.       this.gradient=value;
  761.     }
  762.     else if (cmd=='shadow'){
  763.       this.shadowOn=value;
  764.     }
  765.     else if(cmd=='linestyle'){
  766.         this.lineStyle=value;
  767.     }
  768.      else if(cmd=='fontSize'){
  769.         this.font.size=value;
  770.     }
  771.     else if(cmd=='fontFamily'){
  772.         this.font.family=value;
  773.     }
  774.     else if(cmd=='bold'){
  775.         if(this.font.bold=='bold'){
  776.             this.font.bold='normal';
  777.         }
  778.         else{
  779.             this.font.bold='bold';
  780.         }
  781.     }
  782.      else if(cmd=='italic'){
  783.         if(this.font.italics=='italic'){
  784.             this.font.italics='normal';
  785.         }
  786.         else{
  787.             this.font.italics='italic';
  788.         }
  789.     }
  790.      else if(cmd=='fontColor'){
  791.         this.font.color=value;
  792.     }
  793.      else if(cmd=='align'){
  794.         this.font.align=value;
  795.     }
  796.   }
  797.   else {
  798.     
  799.     this.renderer.editCommand(this.selected, cmd, value,this.zoom);
  800.     if(this.textEditMode==true){
  801.         if(cmd=='fontColor'||cmd=='align'||cmd=='italic'||cmd=='bold'||cmd=='fontFamily'||cmd=='fontSize')
  802.             this.setTextAreaFont($('__shapeText'));
  803.     
  804.     }
  805.   }
  806. }
  807.  
  808. /**
  809. * set the page width and heigh and zoom it according to current zoom factor
  810. **/
  811. RichDrawEditor.prototype.setPageSize=function(width,height){
  812.     if(width>this.MAX_WIDTH){
  813.         setHelp("<font color='red'>Maximum width allowed is:"+this.MAX_WIDTH+"</font>");
  814.     }
  815.     else if(height>this.MAX_HEIGHT){
  816.         setHelp("<font color='red'>Maximum height allowed is:"+this.MAX_HEIGHT+"</font>");
  817.         
  818.     }
  819.     else{
  820.         this.width=width;
  821.         this.height=height;
  822.         this.page.style.width=(this.width*this.zoom)+'px';
  823.         this.page.style.height=(this.height*this.zoom)+'px';
  824.     }
  825.     this.updateShapeInfo(null);
  826.     
  827. }
  828. /**
  829. *get the page size and width return as an array with elements "width", "height"
  830. **/
  831. RichDrawEditor.prototype.getPageSize=function(){
  832.     var size=new Array();
  833.     size['width']=this.width;
  834.     size['height']=this.height;
  835.     return size;
  836. }
  837. /**zoom functions**/
  838. /**
  839. *set zoom: first set the zoom for the container, then call setShapeZoom for shapes
  840. **/
  841. RichDrawEditor.prototype.setZoom=function(value){
  842.     
  843.     value=(this.zoom*value).toFixed(2);
  844.     if(value<0.15||value>4.0)return;
  845.     this.prevZoom=this.zoom;
  846.     this.zoom=value;
  847.     var width=this.page.style.width.split('px')[0];
  848.     var height=this.page.style.height.split('px')[0];
  849.     width=Math.round(width*(value/this.prevZoom));
  850.     height=Math.round(height*(value/this.prevZoom));
  851.     this.page.style.width=width+'px';
  852.     this.page.style.height=height+'px';
  853.     this.setShapeZoom(this.container,value,this.prevZoom);
  854. }
  855. /**
  856. *set the zoom on all individual shapes, call setLineZoom for lines
  857. **/
  858. RichDrawEditor.prototype.setShapeZoom=function(doc,value,prevZoom){
  859.     this.renderer.remove($('tracker-group'));
  860.     this.renderer.remove($('active-shape-tracker'));
  861.     var nodes=this.renderer.getAllShapes(doc);
  862.     var length=nodes.length;
  863.     for(var i=0;i<nodes.length;i++){
  864.         
  865.         var shape=nodes[i];
  866.         var rect=this.renderer.bounds(shape);
  867.         
  868.         this.renderer.setWidth(shape,Math.round(parseFloat(rect['width'])*(value/prevZoom)));
  869.         this.renderer.setHeight(shape,Math.round(parseFloat(rect['height'])*(value/prevZoom)));
  870.         
  871.         this.renderer.setY(shape,Math.round(parseFloat(rect['y'])*(value/prevZoom)));
  872.         this.renderer.setX(shape,Math.round(parseFloat(rect['x'])*(value/prevZoom)));
  873.         this.renderer.updateRotation(shape);
  874.         var text=this.renderer.getShapeText(shape,doc);
  875.         var font=this.renderer.getFont(shape);
  876.         this.renderer.clearShapeText(shape);
  877.         if(text)
  878.                 this.renderer.setShapeText(shape,text,this.font,false,font,value);
  879.  
  880.     }
  881.     
  882.     this.setLineZoom(doc,value,prevZoom);
  883.     this.renderer.updateTracker(this.selected);
  884. }
  885.  
  886. /**
  887. *now set the zoom on all lines
  888. **/
  889. RichDrawEditor.prototype.setLineZoom=function(doc,value,prevZoom){
  890.     var nodes=this.renderer.getAllConnectors(doc);
  891.     var length=nodes.length;
  892.     for(var i=0;i<nodes.length;i++){
  893.         var shape=nodes[i];
  894.         var    fromX=this.renderer.getConnectorFromX(shape) * (value/prevZoom);
  895.         var    fromY=this.renderer.getConnectorFromY(shape) * (value/prevZoom);
  896.         var    toX=this.renderer.getConnectorToX(shape) *(value/prevZoom);
  897.         var    toY=this.renderer.getConnectorToY(shape)*(value/prevZoom);
  898.         this.renderer.moveLinePoint(shape,fromX,fromY,true);
  899.         this.renderer.moveLinePoint(shape,toX,toY,false);
  900.         //now get the control points if any
  901.         if(this.renderer.getConnectorType(shape)=='curve-line'){
  902.             var control1=this.renderer.getControl1(shape);
  903.             var cx1=control1.x* (value/prevZoom);
  904.             var cy1=control1.y*(value/prevZoom);
  905.             this.renderer.setControl1(shape,cx1,cy1);
  906.             var control2=this.renderer.getControl2(shape);
  907.             var cx2=control2.x* (value/prevZoom);
  908.             var cy2=control2.y*(value/prevZoom);
  909.             this.renderer.setControl2(shape,cx2,cy2);
  910.         }
  911.         
  912.         var text=this.renderer.getShapeText(shape,doc);
  913.         var font=this.renderer.getFont(shape);
  914.         this.renderer.clearShapeText(shape);
  915.         if(text)
  916.                 this.renderer.setShapeText(shape,text,this.font,false,font,value,doc);
  917.  
  918.     }
  919. }    
  920. /**
  921. *get zoom factor
  922. **/
  923. RichDrawEditor.prototype.getZoom=function(){
  924.     return this.zoom;
  925. }
  926.  
  927. /**
  928. *return the current value for various commands e.g current fill value, opacity etc. If the shape is selected, the command is delegated
  929. *to the renderer, otherwise handled by the editor
  930. **/
  931. RichDrawEditor.prototype.queryCommand = function(cmd)
  932. {
  933.   if (cmd == 'mode') {
  934.     return this.mode;
  935.   }
  936.   else if (this.selected == null) {
  937.     if (cmd == 'fillcolor') {
  938.       return this.fillColor;
  939.     }
  940.     else if (cmd == 'linecolor') {
  941.       return this.lineColor;
  942.     }
  943.     else if (cmd == 'linewidth') {
  944.       return this.lineWidth;
  945.     }
  946.     else if(cmd=='opacity'){
  947.         return this.opacity;
  948.     }
  949.     else if(cmd=='gradient'){
  950.         return this.gradient;
  951.     }
  952.      else if(cmd=='shadow'){
  953.         return this.shadowOn;
  954.     }
  955.     else if(cmd=='fontSize'){
  956.         return this.font.size;
  957.     }
  958.     else if(cmd=='fontFamily'){
  959.         return this.font.family;
  960.     }
  961.     else if(cmd=='bold'){
  962.         return this.font.bold;
  963.     }
  964.      else if(cmd=='italics'){
  965.         return this.font.italics;
  966.     }
  967.      else if(cmd=='fontColor'){
  968.         return this.font.color;
  969.     }
  970.      else if(cmd=='align'){
  971.         return this.font.align;
  972.     }
  973.     else if(cmd=='font'){
  974.         return this.font;
  975.     }
  976.     else if(cmd=='linedashstyle'){
  977.         return this.linedashstyle;
  978.     }
  979.     else if(cmd=='linestyle'){
  980.         return this.lineStyle;
  981.     }
  982.   }
  983.   else {
  984.     return this.renderer.queryCommand(this.selected, cmd);
  985.   }
  986. }
  987.  
  988.  
  989. RichDrawEditor.prototype.onSelectStart = function(event) {
  990.   return false;
  991. }
  992. /**
  993. * for efficieny purposes we do not redraw the text everytime a shape is moved, 
  994. *which means that when the move related keys are released,
  995. * we need to reset shape text
  996. **/
  997. RichDrawEditor.prototype.onKeyUp=function(event){
  998.     
  999.     var code=event.keyCode;
  1000.     if((code==46||code==37||code==38||code==39||code==40)&&this.textEditMode==true)
  1001.         return true;
  1002.     if(code==37||code==38||code==39||code==40||code==82||code==76){
  1003.         this.clearShapeText();
  1004.         this.resetShapeText();
  1005.     }
  1006. }
  1007.  
  1008. /**
  1009. *handle various key events
  1010. **/
  1011.  
  1012. RichDrawEditor.prototype.onKeyPress=function(event){
  1013.     var code=event.keyCode;
  1014.     var stop=false;
  1015.     var unicode=event.charCode?event.charCode:event.keyCode;
  1016.     var actualKey=String.fromCharCode(unicode);
  1017.     actualKey=actualKey.toLowerCase();
  1018.     if((code==46||code==37||code==38||code==39||code==40)&&this.textEditMode==true)
  1019.         return;
  1020.     if (gTextEditMode)        
  1021.         return;
  1022.         
  1023.     if(46==code&&!this.textEditMode){
  1024.         if (this.selected)
  1025.             gApplication.transmit('w', 'cmd deleteSelection ' + this.selected.id);
  1026.         this.deleteSelection();
  1027.         stop=true;
  1028.     }
  1029.     //disable fine moves as this will probably generate a lot of traffic for large workspaces.
  1030.     /*else if(37==code&&!this.textEditMode){
  1031.         this.clearShapeText();
  1032.         this.fineMove(1,0,0,0);
  1033.         stop=true;
  1034.     }
  1035.     else if(38==code&&!this.textEditMode){
  1036.         this.clearShapeText();
  1037.         this.fineMove(0,0,1,0);
  1038.         stop=true;
  1039.     }
  1040.     else if(39==code&&!this.textEditMode){
  1041.         this.clearShapeText();
  1042.         this.fineMove(0,1,0,0);
  1043.         stop=true;
  1044.     }
  1045.     else if(40==code&&!this.textEditMode){
  1046.         this.clearShapeText();
  1047.         this.fineMove(0,0,0,1);
  1048.         stop=true;
  1049.     }
  1050.     else if('r'==actualKey){
  1051.         if(event.shiftKey&&!this.textEditMode){
  1052.             this.clearShapeText();
  1053.             this.fineRotateSelection(1);
  1054.             stop=true;
  1055.         }
  1056.     }
  1057.     else if('l'==actualKey){
  1058.         if(event.shiftKey&&!this.textEditMode){
  1059.             this.clearShapeText();
  1060.             this.fineRotateSelection(-1);
  1061.             stop=true;
  1062.         }
  1063.     }*/
  1064.     else if('x'==actualKey){
  1065.         if(event.ctrlKey&&!this.textEditMode)
  1066.         {    this.cut();
  1067.             if (this.selected)
  1068.                 gApplication.transmit('w', 'cmd deleteSelection ' + this.selected.id);
  1069.  
  1070.         }    
  1071.             stop=true;
  1072.     }
  1073.     else if('c'==actualKey){
  1074.         if(event.ctrlKey&&!this.textEditMode)
  1075.             this.copy();
  1076.             stop=true;
  1077.     }
  1078.     else if('v'==actualKey){
  1079.         if(event.ctrlKey&&!this.textEditMode)
  1080.             this.paste();;
  1081.             stop=true;
  1082.     }
  1083.     else if('b'==actualKey){
  1084.         if(event.ctrlKey){
  1085.             this.editCommand("bold");
  1086.             stop=true;
  1087.         }
  1088.     }
  1089.     else if('i'==actualKey){
  1090.         if(event.ctrlKey){
  1091.             this.editCommand("italic");
  1092.             stop=true;
  1093.             
  1094.         }
  1095.     }
  1096.     else{
  1097.         stop=false;
  1098.     }
  1099.     
  1100.     if(stop&&!this.textEditMode){
  1101.         Event.stop(event);
  1102.         return false;
  1103.     }
  1104.     else{
  1105.         return true;
  1106.     }
  1107. }
  1108.  
  1109. /*******************MOUSE OVER***************************/
  1110. /**
  1111. *if the mouse is over the tracker set the appropriate cursor.
  1112. *This method needs some serious cleaning up,
  1113. *there is nothing wrong with it except that the logic could be performed much more elegantly.
  1114. **/
  1115. RichDrawEditor.prototype.onMouseOver=function(event){
  1116.  
  1117.     var source=Event.element(event);
  1118.     if(source.id=='resize-bottom'||source.id=='resize-right'||source.id=="tracker-rotate"||
  1119.     source.id=='resize-left'||source.id=='resize-top'){
  1120.     var offset = Position.cumulativeOffset(this.container);
  1121.     var snappedX = (Event.pointerX(event) - offset[0]) / this.gridX * this.gridX;
  1122.     var snappedY = (Event.pointerY(event) - offset[1]) / this.gridY * this.gridY;
  1123.         
  1124.         var rotation=this.renderer.bounds(this.selected)['rotation'];
  1125.         rotation=rotation%360;
  1126.         if(source.id=='resize-bottom'){
  1127.             source.style.cursor='s-resize';
  1128.             if(rotation!=null&&((rotation>=45&&rotation<=135)||(rotation>=225&&rotation<=315))){
  1129.                 source.style.cursor='e-resize';
  1130.             }
  1131.             else{
  1132.                 source.style.cursor='s-resize';
  1133.             }
  1134.         }
  1135.         else if(source.id=='resize-top'){
  1136.             source.style.cursor='s-resize';
  1137.             if(rotation!=null&&((rotation>=45&&rotation<=135)||(rotation>=225&&rotation<=315))){
  1138.                 source.style.cursor='e-resize';
  1139.             }
  1140.             else{
  1141.                 source.style.cursor='s-resize';
  1142.             }
  1143.         }
  1144.         else if(source.id=='resize-right'){
  1145.             source.style.cursor='e-resize';
  1146.             if(rotation!=null&&((rotation>=45&&rotation<=135)||(rotation>=225&&rotation<=315))){
  1147.                 source.style.cursor='s-resize';
  1148.             }
  1149.             else{
  1150.                 source.style.cursor='e-resize';
  1151.             }
  1152.         }
  1153.          else if(source.id=='resize-left'){
  1154.             source.style.cursor='e-resize';
  1155.             
  1156.             if(rotation!=null&&((rotation>=45&&rotation<=135)||(rotation>=225&&rotation<=315))){
  1157.                 source.style.cursor='s-resize';
  1158.             }
  1159.             else{
  1160.                 source.style.cursor='e-resize';
  1161.             }
  1162.             
  1163.         }
  1164.         else if(source.id=="tracker-rotate"){
  1165.             
  1166.             source.style.cursor='move';
  1167.             this.resizeMode="rotate";
  1168.         }
  1169.         
  1170.     }
  1171.     
  1172.     return false;
  1173. }
  1174.  
  1175. /*******************MOUSE DOWN***************************/
  1176. /**
  1177. *handle mouse down related events, another refactoring candidate, too much going on in here...
  1178. **/
  1179. RichDrawEditor.prototype.onMouseDown = function(event) {
  1180.   
  1181.   var offset = Position.cumulativeOffset(this.container);
  1182.   var snappedX = Math.round((Event.pointerX(event) - offset[0]) / this.gridX) * this.gridX;
  1183.   var snappedY = Math.round((Event.pointerY(event) - offset[1]) / this.gridY) * this.gridY;
  1184.   var source=Event.element(event);
  1185.   if(source.id=='resize-bottom'||source.id=='resize-right'||source.id=="tracker-rotate"||
  1186.     source.id=='resize-left'||source.id=='resize-top'||source.id=='resize-from'||source.id=='resize-to'
  1187.     ||source.id=='control1'||source.id=='control2'){
  1188.     this.prevMode=this.mode;
  1189.     this.setMode('resize');
  1190.         if(this.selected){
  1191.             this.mouseDownX = snappedX;
  1192.             this.mouseDownY = snappedY;
  1193.             var rect=this.renderer.bounds(this.selected);
  1194.             this.prevWidth=rect['width'];
  1195.             this.prevLeft=rect['x'];
  1196.             this.prevHeight=rect['height'];
  1197.             this.prevTop=rect['y'];
  1198.             this.prevRotation=rect['rotation'];
  1199.             if(!this.prevRotation)
  1200.                 this.prevRotation=0;
  1201.             
  1202.              if(source&&source.id){
  1203.                 if(source.id=='resize-from'){
  1204.                     this.resizeMode='line-from';
  1205.                 }
  1206.                 else if(source.id=='resize-to'){
  1207.                     this.resizeMode='line-to';
  1208.                 }
  1209.                 else if(source.id=='control1'){
  1210.                     this.resizeMode='control1';
  1211.                     
  1212.                 }
  1213.                 else if(source.id=='control2'){
  1214.                     this.resizeMode='control2';
  1215.                     
  1216.                 }
  1217.                 else if(source.id=='resize-bottom'){            
  1218.                     this.resizeMode="bottom-stretch";
  1219.                     
  1220.                 }
  1221.                 else if(source.id=='resize-top'){
  1222.                     this.resizeMode="top-stretch";
  1223.                     
  1224.                 }
  1225.                 else if(source.id=='resize-right'){
  1226.                     this.resizeMode="right-stretch";
  1227.                     
  1228.                 }
  1229.                 
  1230.                 else if(source.id=='resize-left'){
  1231.                     this.resizeMode="left-stretch";
  1232.                     
  1233.                 }
  1234.                 else if(source.id=="tracker-rotate"){
  1235.                     this.resizeMode="rotate";
  1236.                     
  1237.                 }
  1238.                 this.clearShapeText();
  1239.             }
  1240.             
  1241.         }
  1242.     
  1243.     
  1244. //    if(this.resizeMode=="rotate"){
  1245. //        setHelp("For Fine rotation use <B>Shift+R</B> and <B>Shift+L</B>");
  1246. //    }
  1247.     Event.observe(this.container, "mousemove", this.onDrawListener);  
  1248.   }
  1249.   else if (this.mode != 'select'&&this.mode!='resize') {
  1250.     
  1251.     this.unselect();
  1252.     setHelp("Drag your mouse to size the selected shape");
  1253.     this.mouseDownX = snappedX;
  1254.     this.mouseDownY = snappedY;
  1255.     if(this.mode!='line'&&this.mode!='ortho-line'&&this.mode!='curve-line'){
  1256.         var mouseX=(this.mouseDownX*1)+this.container.parentNode.scrollLeft;
  1257.         var mouseY=( this.mouseDownY*1)+this.container.parentNode.scrollTop;
  1258.     
  1259.         this.selected = this.renderer.create(this.mode, this.fillColor, this.lineColor, this.lineWidth, mouseX, mouseY, 1, 1,this.opacity,this.gradient,this.shadowOn);
  1260.         this.selected.setAttribute('id', 'shape:' + createUUID());
  1261.         this.addNewShapeListeners(this.selected);
  1262.         if(this.mode=="text"){
  1263.             this.textToolBeginNew=true;
  1264.         }
  1265.     }
  1266.     
  1267.     else{
  1268.         var mouseX=(this.mouseDownX*1)+this.container.parentNode.scrollLeft;
  1269.         var mouseY=( this.mouseDownY*1)+this.container.parentNode.scrollTop;
  1270.         this.unselect();
  1271.         this.selected = this.renderer.createLine(this.mode, this.lineColor, this.lineWidth, mouseX, mouseY,this.lineStyle);
  1272.         this.selected.setAttribute('id', 'connector:' + createUUID());
  1273.         this.addNewShapeListeners(this.selected);
  1274.     
  1275.     }
  1276.     Event.observe(this.container, "mousemove", this.onDrawListener);  
  1277.     this.renderer.setCursor(this.container,'crosshair');
  1278.   }
  1279.   else {
  1280.     if (this.mouseDownX != snappedX || this.mouseDownY != snappedY)
  1281.       this.unselect();
  1282.   }
  1283.   
  1284.   return false;
  1285. };
  1286. RichDrawEditor.prototype.isLineDrawMode=function(){
  1287.     return (this.mode=='line'||this.resizeMode=='line-from'||this.resizeMode=='line-to'||this.mode=='ortho-line'
  1288.         ||this.mode=='curve-line')
  1289. }
  1290. /**
  1291. *if the mode is line draw then show connection points
  1292. **/
  1293. RichDrawEditor.prototype.onShapeMouseEnter=function(event){
  1294.     var source=Event.element(event);
  1295.     var shape=this.renderer.getShapeFromEventSource(source);
  1296.     //setHelp(shape.id);
  1297.     if(!this.renderer.isConnector(shape)){
  1298.         var newActiveShape=shape;
  1299.         if((this.lineActiveShape&&newActiveShape&&this.lineActiveShape.id==newActiveShape.id)&&newActiveShape.id)
  1300.         //revisit this
  1301.         // ||(newActiveShape.id&&newActiveShape.id.indexof("shape")<0))
  1302.             return;
  1303.         else{
  1304.         
  1305.         
  1306.         if(this.isLineDrawMode()){
  1307.             this.renderer.remove($("active-shape-tracker"));
  1308.             this.lineActiveShape=newActiveShape;
  1309.             
  1310.             this.renderer.showConnectionPoints(this.lineActiveShape);
  1311.         }
  1312.     }
  1313.     }
  1314.     if(!this.isLineDrawMode()&&this.mode!='text'){
  1315.         
  1316.         this.renderer.setCursor(this.container,"move");
  1317.         
  1318.     }
  1319. };
  1320.  
  1321. /*******************MOUSE OUT***************************/
  1322.  
  1323. RichDrawEditor.prototype.onShapeMouseOut=function(event){
  1324.     if(!this.isLineDrawMode()&&this.mode!="text")
  1325.         this.renderer.setCursor(this.container,"default");
  1326. }
  1327.  
  1328. /**
  1329. *if the mouse leaves the container, stop listening to some events 
  1330. **/
  1331. RichDrawEditor.prototype.onMouseOut=function(event){
  1332.     
  1333.     if(event.toElement&&(event.toElement.id=='_body'||event.toElement.id=='_surround'||event.toElement.id=="palette")){
  1334.     
  1335.     if((this.mode!='resize'&&this.mode!='select'&&this.mode!="text"))
  1336.     {
  1337.         var transmitData = this.copyToRemote();
  1338.         if (transmitData != null)
  1339.             gApplication.transmit('w', "cpy " + transmitData);
  1340.     }
  1341.     else if (this.selected)
  1342.     {
  1343.         var rect=new Object();
  1344.         rect=this.renderer.bounds(this.selected);
  1345.         if(!this.renderer.isConnector(this.selected))
  1346.         {
  1347.             //a shape
  1348.             rect['x']=(rect['x']*(1.0/this.zoom)).toFixed(0);
  1349.             rect['y']=(rect['y']*(1.0/this.zoom)).toFixed(0);
  1350.             rect['width']=(rect['width']*(1.0/this.zoom)).toFixed(0);
  1351.             rect['height']=(rect['height']*(1.0/this.zoom)).toFixed(0);
  1352.             var transmitData = "mvs " + this.selected.id + " " + rect['width'] + " " + rect['height'] + " " + rect['x'] + " " + rect['y'] + " " + rect['rotation'];
  1353.  
  1354.         }
  1355.         else{
  1356.             //a connector
  1357.             rect['x']=(rect['x']*(1.0/this.zoom)).toFixed(0);
  1358.             rect['y']=(rect['y']*(1.0/this.zoom)).toFixed(0);
  1359.             rect['x2']=(rect['x2']*(1.0/this.zoom)).toFixed(0);
  1360.             rect['y2']=(rect['y2']*(1.0/this.zoom)).toFixed(0);
  1361.             var transmitData = "mvc " + this.selected.id + " " + rect['x'] + " " + rect['x2'] + " " + rect['y'] + " " + rect['y2'] + " " + rect['type'];
  1362.         }
  1363.         gApplication.transmit('w', transmitData);
  1364.     }
  1365.  
  1366.  
  1367.  
  1368.         Event.stopObserving(this.container, "mousemove", this.onDrawListener);  
  1369.         Event.stopObserving(this.container, "mousemove", this.onDragListener);  
  1370.     }
  1371. }
  1372.  
  1373. /**
  1374. *respond to various mouse up events
  1375. */
  1376. RichDrawEditor.prototype.onMouseUp = function(event)
  1377. {
  1378.  
  1379.     if (this.mode != 'select'&&this.mode!='resize'&&this.mode!='line'&&this.mode!='ortho-line')
  1380.     {
  1381.         setHelp("Click on the shape to select it");
  1382.     }
  1383.   
  1384.     if((this.mode!='resize'&&this.mode!='select'&&this.mode!="text"))
  1385.     {
  1386.         var transmitData = this.copyToRemote();
  1387.         if (transmitData != null)
  1388.             gApplication.transmit('w', "cpy " + transmitData);
  1389.     }
  1390.     else if (this.selected)
  1391.     {
  1392.         var rect=new Object();
  1393.         rect=this.renderer.bounds(this.selected);
  1394.         if(!this.renderer.isConnector(this.selected))
  1395.         {
  1396.             //a shape
  1397.             rect['x']=(rect['x']*(1.0/this.zoom)).toFixed(0);
  1398.             rect['y']=(rect['y']*(1.0/this.zoom)).toFixed(0);
  1399.             rect['width']=(rect['width']*(1.0/this.zoom)).toFixed(0);
  1400.             rect['height']=(rect['height']*(1.0/this.zoom)).toFixed(0);
  1401.             var transmitData = "mvs " + this.selected.id + " " + rect['width'] + " " + rect['height'] + " " + rect['x'] + " " + rect['y'] + " " + rect['rotation'];
  1402.  
  1403.         }
  1404.         else{
  1405.             //a connector
  1406.             rect['x']=(rect['x']*(1.0/this.zoom)).toFixed(0);
  1407.             rect['y']=(rect['y']*(1.0/this.zoom)).toFixed(0);
  1408.             rect['x2']=(rect['x2']*(1.0/this.zoom)).toFixed(0);
  1409.             rect['y2']=(rect['y2']*(1.0/this.zoom)).toFixed(0);
  1410.             var transmitData = "mvc " + this.selected.id + " " + rect['x'] + " " + rect['x2'] + " " + rect['y'] + " " + rect['y2'] + " " + rect['type'];
  1411.         }
  1412.         gApplication.transmit('w', transmitData);
  1413.     }
  1414.  
  1415.     Event.stopObserving(this.container, "mousemove", this.onDrawListener);
  1416.     Event.stopObserving(this.container, "mousemove", this.onDragListener);
  1417.  
  1418.     if(this.dragStarted)
  1419.     {
  1420.           this.clearShapeText();
  1421.           this.resetShapeText(); 
  1422.           this.dragStarted=false;
  1423.     }
  1424.     
  1425.     if(this.mode=='line'||this.mode=='curve-line'||this.resizeMode=='line-from'||this.resizeMode=='line-to'||this.mode=='ortho-line')
  1426.     {
  1427.         //todo add show marker logic here
  1428.         if(this.resizeMode=='line-from')
  1429.             this.renderer.connectLine(this.lineActiveShape,this.selected,"from");
  1430.         else if(this.resizeMode=='line-to'||this.mode=='line'||this.mode=='ortho-line'||this.mode=='curve-line')
  1431.             this.renderer.connectLine(this.lineActiveShape,this.selected,"to");
  1432.         
  1433.         this.renderer.remove($('active-shape-tracker'));
  1434.         this.lineActiveShape=null;
  1435.           this.clearShapeText();
  1436.           this.resetShapeText(); 
  1437.     }
  1438.     if(this.mode=="text"&&this.textToolBeginNew){
  1439.           this.beginTextToolEdit(this.selected);
  1440.           this.textToolBeginNew=false;
  1441.     }
  1442.     else if(this.mode=="text"&&!this.textToolBeginNew){
  1443.           setHelp("<font color='red'>Text Mode:</font>Click again to draw another text shape");
  1444.  
  1445.         var transmitData = this.copyToRemote();
  1446.         if (transmitData != null)
  1447.             gApplication.transmit('w', "cpy " + transmitData);
  1448.       
  1449.     }
  1450.     if(this.mode=='resize'){
  1451.           Event.stopObserving(this.container, "mousemove", this.onDrawListener); 
  1452.           this.clearShapeText();
  1453.           this.resetShapeText(); 
  1454.           this.setMode(this.prevMode);
  1455.           this.resizeMode="";
  1456.     }
  1457.       
  1458.     if (this.mode != 'select'&&this.mode!='line'&&this.mode!='ortho-line'&&this.mode!="text"&&this.mode!='curve-line') {
  1459.         this.setMode('select');
  1460.     }
  1461.     else{
  1462.         //mainly to refresh the cursor!!!
  1463.         this.setMode(this.mode);
  1464.     } 
  1465.  
  1466.   
  1467. };
  1468. /**
  1469. *begin text tool edit will first set the stroke-width to 0 and then start text editing
  1470. *@param {shape} selected shape
  1471. **/
  1472. RichDrawEditor.prototype.beginTextToolEdit=function(shape){
  1473.     this.renderer.setStrokeWidth(shape,"0px");
  1474.     this.renderer.setOpacity(shape,"0.0");
  1475.     this.startTextEdit(shape);
  1476. }
  1477. /*****************ON DRAG**********************/
  1478. /**
  1479. *move the shape
  1480. **/
  1481. RichDrawEditor.prototype.onDrag = function(event) {
  1482.   var offset = Position.cumulativeOffset(this.container);
  1483.   var snappedX = Math.round((Event.pointerX(event) - offset[0]) / this.gridX) * this.gridX;
  1484.   var snappedY = Math.round((Event.pointerY(event) - offset[1]) / this.gridY) * this.gridY;
  1485.  
  1486.   var deltaX = snappedX - this.mouseDownX;
  1487.   var deltaY = snappedY - this.mouseDownY;
  1488.   if(!this.dragStarted==true){
  1489.       this.clearShapeText();
  1490.       this.dragStarted=true;
  1491.   }
  1492.   if(this.renderer.isConnector(this.selected)){
  1493.     this.renderer.disconnectLineFromShape(this.selected,"to");
  1494.     this.renderer.disconnectLineFromShape(this.selected,"from");
  1495.     this.renderer.moveCompleteLine(this.selected,this.selectedBounds,deltaX,deltaY);
  1496.     this.clearShapeText();
  1497.   }
  1498.   else{
  1499.      
  1500.       this.renderer.move(this.selected, (this.selectedBounds.x*1) + deltaX, (this.selectedBounds.y*1) + deltaY);
  1501.       this.renderer.moveLineWithShape(this.selected);
  1502.   }
  1503.   // Update selection tracker
  1504.   this.renderer.updateTracker(this.selected);
  1505.   this.updateShapeInfo(this.selected);
  1506. };
  1507.  
  1508. /**
  1509. *move 1px at a time--reacting to arrow key press
  1510. **/
  1511. RichDrawEditor.prototype.fineMove=function(left,right,up,down){
  1512.     if(this.selected){
  1513.         if(this.renderer.isConnector(this.selected)) return;
  1514.         var deltaX=right-left;
  1515.         var deltaY=down-up;
  1516.         //this.selectedBounds = this.renderer.bounds(this.selected);
  1517.         if(deltaY==0){
  1518.             this.renderer.fineMove(this.selected, deltaX, true);
  1519.         }
  1520.         else{
  1521.             this.renderer.fineMove(this.selected,  deltaY, false);
  1522.         }
  1523.     
  1524.         this.renderer.moveLineWithShape(this.selected);
  1525.         this.renderer.updateTracker(this.selected);
  1526.         //this.updateShapeInfo(this.selected);
  1527.         this.selectedBounds = this.renderer.bounds(this.selected);
  1528.     }
  1529.     else{
  1530.         setHelp("Select a shape for Fine move");
  1531.     }
  1532.  
  1533. }
  1534.  
  1535. /**************ON DRAW*****************/
  1536. /**
  1537. *either create new or resize existing
  1538. **/
  1539. RichDrawEditor.prototype.onDraw = function(event) {
  1540.   if (this.selected == null)
  1541.     return;
  1542.  
  1543.  
  1544.   var offset = Position.cumulativeOffset(this.container);
  1545.   var snappedX = Math.round((Event.pointerX(event) - offset[0]) / this.gridX) * this.gridX;
  1546.   var snappedY = Math.round((Event.pointerY(event) - offset[1]) / this.gridY) * this.gridY;
  1547.   
  1548.   
  1549.   //this means we are drawing a new shape or line on the canvas
  1550.   
  1551.   if(this.mode!='resize'&&this.mode!='select'){
  1552.     var mouseX=(this.mouseDownX*1)+this.container.parentNode.scrollLeft;
  1553.     var mouseY=( this.mouseDownY*1)+this.container.parentNode.scrollTop;
  1554.     var sx=(snappedX*1)+this.container.parentNode.scrollLeft;
  1555.     var sy=(snappedY*1)+this.container.parentNode.scrollTop;
  1556.     this.renderer.resize(this.selected, mouseX,mouseY,sx,sy);
  1557.     this.updateShapeInfo(this.selected);
  1558.     //we show tracker during draw only for connectors
  1559.     if(this.renderer.isConnector(this.selected)){
  1560.           this.renderer.updateTracker(this.selected);
  1561.           
  1562.       }
  1563.       return;
  1564.   }
  1565.   
  1566.   //otherwise check the resize mode, if the mode is horizontal then keep left static
  1567.   //otherwise if mode is vertical keep the top static
  1568.   
  1569.   if(this.mode=='resize'||this.mode=='select'){
  1570.           this.resizeCounter++;
  1571.           if(this.resizeCounter!=2){
  1572.               return;
  1573.           }
  1574.           this.resizeCounter=0;
  1575.       
  1576.       if(this.resizeMode=="line-from"){
  1577.           
  1578.         var sx=(snappedX*1)+this.container.parentNode.scrollLeft;
  1579.         var sy=(snappedY*1)+this.container.parentNode.scrollTop;
  1580.         this.renderer.disconnectLineFromShape(this.selected,"from");
  1581.           this.renderer.moveLine(this.selected,sx,sy,true);
  1582.           
  1583.           
  1584.       }
  1585.       else if(this.resizeMode=="line-to"){
  1586.           var sx=(snappedX*1)+this.container.parentNode.scrollLeft;
  1587.         var sy=(snappedY*1)+this.container.parentNode.scrollTop;
  1588.         
  1589.         this.renderer.disconnectLineFromShape(this.selected,"to");
  1590.           this.renderer.moveLine(this.selected,sx,sy,false);
  1591.           
  1592.           
  1593.       }
  1594.       //add control point listeners
  1595.       else if(this.resizeMode=="control1"){
  1596.           var sx=(snappedX*1)+this.container.parentNode.scrollLeft;
  1597.         var sy=(snappedY*1)+this.container.parentNode.scrollTop;
  1598.           this.renderer.setControl1(this.selected,sx,sy);
  1599.           
  1600.           
  1601.       }
  1602.       else if(this.resizeMode=="control2"){
  1603.           var sx=(snappedX*1)+this.container.parentNode.scrollLeft;
  1604.         var sy=(snappedY*1)+this.container.parentNode.scrollTop;
  1605.           this.renderer.setControl2(this.selected,sx,sy);
  1606.           
  1607.           
  1608.       }
  1609.       //use this for right pull
  1610.       if(this.resizeMode=="right-stretch"){
  1611.           this.renderer.resizeWidth(this.selected, snappedX,snappedY, this.mouseDownX,this.mouseDownY,this.prevWidth,true);
  1612.           this.renderer.moveLineWithShape(this.selected);
  1613.       }
  1614.       else 
  1615.       if(this.resizeMode=="left-stretch"){
  1616.           
  1617.           this.renderer.resizeWidth(this.selected, snappedX,snappedY, this.mouseDownX,this.mouseDownY,this.prevWidth,false);
  1618.           this.renderer.moveLineWithShape(this.selected);
  1619.       }
  1620.       //use this for bottom pull
  1621.       else if(this.resizeMode=="bottom-stretch"){
  1622.           this.renderer.resizeHeight(this.selected, snappedX,snappedY, this.mouseDownX,this.mouseDownY,this.prevHeight,true);
  1623.           this.renderer.moveLineWithShape(this.selected);
  1624.       }
  1625.       else if(this.resizeMode=="top-stretch"){
  1626.           this.renderer.resizeHeight(this.selected, snappedX,snappedY, this.mouseDownX,this.mouseDownY,this.prevHeight,false);
  1627.           this.renderer.moveLineWithShape(this.selected);
  1628.       }
  1629.       else if(this.resizeMode=="rotate"){
  1630.           var mouseX=(this.mouseDownX*1)+this.container.parentNode.scrollLeft;
  1631.         var mouseY=( this.mouseDownY*1)+this.container.parentNode.scrollTop;
  1632.         var sx=(snappedX*1)+this.container.parentNode.scrollLeft;
  1633.         var sy=(snappedY*1)+this.container.parentNode.scrollTop;
  1634.           this.processRotate(this.selected, sx,sy,mouseX,mouseY);
  1635.           this.renderer.moveLineWithShape(this.selected);
  1636.       }
  1637.       this.renderer.updateTracker(this.selected);
  1638.       this.updateShapeInfo(this.selected);
  1639.       
  1640.   }
  1641.     return false;
  1642. };
  1643. /*******************ROTATION FUNCTIONS**********************/
  1644. /**
  1645. *rotate 1 degree at a time
  1646. **/
  1647. RichDrawEditor.prototype.fineRotateSelection=function(angle){
  1648.     if(this.selected==null){
  1649.     setHelp("Please select a shape to rotate");
  1650.     return false;
  1651.     }
  1652.     //this.selectedBounds = this.renderer.bounds(this.selected);
  1653.     this.renderer.fineRotateSelection(this.selected,angle);
  1654.     this.renderer.moveLineWithShape(this.selected);
  1655.     this.renderer.updateTracker(this.selected);
  1656.     
  1657.     this.selectedBounds = this.renderer.bounds(this.selected);
  1658. }
  1659.  
  1660. /**
  1661. * this method obtains the actual number of degrees to rotate by, renderer performs the actual rotation
  1662. *@param snappedX (currentX)
  1663. *@param snappedY (currentY)
  1664. *@param mouseDownX
  1665. *@param mouseDownY
  1666. **/
  1667. RichDrawEditor.prototype.processRotate=function(shape,snappedX,snappedY,mouseDownX,mouseDownY){
  1668.     var rect=this.renderer.bounds(shape);
  1669.     var centerX=(rect['x']*1)+(rect['width']/2);
  1670.     var centerY=(rect['y']*1)+(rect['height']/2);
  1671.     //first translate snapped x and y to origin
  1672.     var transX=snappedX-centerX;
  1673.     var transY=snappedY-centerY;
  1674.     //now we are at origin, our arbitrary point would be 0,-10
  1675.     //now take the dot product
  1676.     var adotb=(transX*0)+(transY*(-10));
  1677.     //now cros product |A|*|B|=sqrt((x1square+y1square))*sqrt((x2square+y2square));
  1678.     //we know sqrt((x1square+y1square))=10
  1679.     var acrossb=(10)*Math.sqrt((transX*transX)+(transY*transY));
  1680.     var theta=adotb/acrossb;
  1681.     theta=Math.acos(theta);
  1682.     theta=rad2Deg(theta)
  1683.     //if in quadrant 3 or 4
  1684.     if(transX<=0)theta=360-theta;
  1685.     
  1686.     this.renderer.rotate(this.selected,Math.round(theta));
  1687.     
  1688.     
  1689. }
  1690. /******************* END ROTATION FUNCTIONS**********************/
  1691.  
  1692. /**
  1693. *basically when a shape is has a mouse hit...select it. If we are in text edit mode,
  1694. *do nothing, just return;
  1695. *@param the event
  1696. **/
  1697. RichDrawEditor.prototype.onHit = function(event) {
  1698.   if(this.textEditMode){
  1699.           return;
  1700.   }
  1701.  
  1702.   if (this.mode == 'select') {
  1703.     this.unselect();
  1704.     var source=Event.element(event);
  1705.     this.select(this.renderer.getShapeFromEventSource(source));
  1706.     this.selectedBounds = this.renderer.bounds(this.selected);
  1707.     var offset = Position.cumulativeOffset(this.container);
  1708.     this.mouseDownX = Math.round((Event.pointerX(event) - offset[0]) / this.gridX) * this.gridX;
  1709.     this.mouseDownY = Math.round((Event.pointerY(event) - offset[1]) / this.gridY) * this.gridY;
  1710.     Event.observe(this.container, "mousemove", this.onDragListener);  
  1711.   }
  1712. };
  1713. /**
  1714. * update the properties box with shape or page info
  1715. * @param the shape
  1716. **/
  1717. RichDrawEditor.prototype.updateShapeInfo=function(selected){
  1718.     var rect=new Object();
  1719.     if(selected==null){
  1720.         //show page properties
  1721.         rect['width'] =  this.width;
  1722.         rect['height'] = this.height;
  1723.         this.pageProps.width.value=rect['width'];
  1724.         this.pageProps.height.value=rect['height'];
  1725.         
  1726.         this.shapeProps.table.style.visibility="hidden";
  1727.         this.shapeProps.table.style.display="none";
  1728.         this.pageProps.table.style.visibility="visible";
  1729.         this.pageProps.table.style.display="";
  1730.         this.lineProps.table.style.visibility="hidden";
  1731.         this.lineProps.table.style.display="none";
  1732.     }
  1733.     else{
  1734.         
  1735.         rect=this.renderer.bounds(selected);
  1736.         //this is a shape
  1737.         if(!this.renderer.isConnector(selected)){
  1738.             rect['x']=(rect['x']*(1.0/this.zoom)).toFixed(0);
  1739.             rect['y']=(rect['y']*(1.0/this.zoom)).toFixed(0);
  1740.             rect['width']=(rect['width']*(1.0/this.zoom)).toFixed(0);
  1741.             rect['height']=(rect['height']*(1.0/this.zoom)).toFixed(0);
  1742.             this.shapeProps.width.value=rect['width'];
  1743.                this.shapeProps.height.value=rect['height'];
  1744.             this.shapeProps.x.value=rect['x'];
  1745.             this.shapeProps.y.value=rect['y'];    
  1746.                this.shapeProps.rotation.value=rect['rotation'];
  1747.             this.shapeProps.table.style.visibility="visible";
  1748.             this.shapeProps.table.style.display="";
  1749.             this.lineProps.table.style.visibility="hidden";
  1750.             this.lineProps.table.style.display="none";
  1751.             this.pageProps.table.style.visibility="hidden";
  1752.             this.pageProps.table.style.display="none";
  1753.         }
  1754.         else{
  1755.             //its a connector
  1756.             rect['x']=(rect['x']*(1.0/this.zoom)).toFixed(0);
  1757.             rect['y']=(rect['y']*(1.0/this.zoom)).toFixed(0);
  1758.             rect['x2']=(rect['x2']*(1.0/this.zoom)).toFixed(0);
  1759.             rect['y2']=(rect['y2']*(1.0/this.zoom)).toFixed(0);
  1760.             this.lineProps.x1.innerHTML=rect['x'];
  1761.             this.lineProps.x2.innerHTML=rect['x2'];
  1762.             this.lineProps.y1.innerHTML=rect['y'];
  1763.             this.lineProps.y2.innerHTML=rect['y2'];
  1764.             this.lineProps.type.innerHTML=rect['type'];
  1765.             this.shapeProps.table.style.visibility="hidden";
  1766.             this.shapeProps.table.style.display="none";
  1767.             this.lineProps.table.style.visibility="visible";
  1768.             this.lineProps.table.style.display="";
  1769.             this.pageProps.table.style.visibility="hidden";
  1770.             this.pageProps.table.style.display="none";
  1771.         
  1772.         }
  1773.     }
  1774.     
  1775. };
  1776. /**
  1777. * append a cumulate draw specific page attribute to the save data
  1778. **/
  1779. RichDrawEditor.prototype.appendPageAttribute=function(div,attribute){
  1780.     this.renderer.appendPageAttribute(div,attribute);
  1781. }
  1782. /**
  1783. *get the vml/svg data embedded in the richdraw editor
  1784. **/
  1785. RichDrawEditor.prototype.getRealData=function(){
  1786.     return this.renderer.getRealData();
  1787. }
  1788. /**
  1789. *take the response text and return valid data from it
  1790. **/
  1791. RichDrawEditor.prototype.getValidDocumentFromResponse=function(response){
  1792.     return this.renderer.getValidDocumentFromResponse(response);
  1793.  
  1794. }
  1795. /**
  1796. *load palette, does this really belong in the editor?
  1797. **/
  1798. RichDrawEditor.prototype.loadPalette=function(id){
  1799.     
  1800.     var object=this.renderer.loadXML("shapes/palettes/"+id+".xml");
  1801.     
  1802.     return object.getElementsByTagName("palette")[0];
  1803.  
  1804. }
  1805. /**
  1806. *method to update the shape properties, take zoom factor into account here and also
  1807. *move any connectors attached to the shape
  1808. **/
  1809. RichDrawEditor.prototype.updateShape=function(width,height,x,y,rotation){
  1810.     
  1811.     if(this.selected){
  1812.         var rect=this.selected;
  1813.         width=(width*(this.zoom/1.0)).toFixed(0);
  1814.         height=(height*(this.zoom/1.0)).toFixed(0);
  1815.         x=(x*(this.zoom/1.0)).toFixed(0);
  1816.         y=(y*(this.zoom/1.0)).toFixed(0);
  1817.         this.renderer.setWidth(this.selected,width);
  1818.         this.renderer.setHeight(this.selected,height);
  1819.         this.renderer.setX(this.selected,x);
  1820.         this.renderer.setY(this.selected,y);    
  1821.         this.renderer.setRotation(this.selected,rotation);
  1822.         this.renderer.updateTracker(this.selected);
  1823.         this.renderer.moveLineWithShape(this.selected);
  1824.         this.clearShapeText(this.selected);
  1825.         this.resetShapeText(this.selected);
  1826.         
  1827.     } else{
  1828.         setHelp("Please select a shape to update");
  1829.     }
  1830. }
  1831.  
  1832. /**
  1833. *utility function to convert rad to degrees
  1834. **/
  1835.  
  1836. function rad2Deg(angle){
  1837.     return angle * (180 / Math.PI);
  1838. }
  1839.  
  1840. /**
  1841. *create a unique id for shapes
  1842. **/
  1843. function createUUID()
  1844. {
  1845.   return [4, 2, 2, 2, 6].map(function(length) {
  1846.     var uuidpart = "";
  1847.     for (var i=0; i<length; i++) {
  1848.       var uuidchar = parseInt((Math.random() * 256)).toString(16);
  1849.       if (uuidchar.length == 1)
  1850.         uuidchar = "0" + uuidchar;
  1851.       uuidpart += uuidchar;
  1852.     }
  1853.     return uuidpart;
  1854.   }).join('-');
  1855. }
  1856.  
  1857. function show(object){document.getElementById(object).style.visibility='visible';document.getElementById(object).style.display='';}
  1858.  
  1859. function hide(object){document.getElementById(object).style.visibility='hidden';document.getElementById(object).style.display='none';}
  1860.  
  1861.  
  1862. RichDrawEditor.prototype.setUser=function(aUser){
  1863. this.iUser=aUser;
  1864. }
  1865.  
  1866. RichDrawEditor.prototype.handleRemoteCommand=function(param)
  1867. {
  1868.     var name = param.substr(0,param.indexOf(" "));
  1869.     var remoteData = param.substr(param.indexOf(" ")+1);
  1870.  
  1871.     var command = remoteData.substring(0,3);
  1872.     var content = remoteData.substring(4);
  1873.     if (command=="ann")
  1874.     {
  1875.         //announce start of a drawing
  1876.         insertInvitation(name);
  1877.     }
  1878.     else if (command=="stp")
  1879.     {
  1880.         //announce end of a drawing
  1881.         removeInvitation(name);
  1882.         gApplication.removePeer(name);
  1883.     }
  1884.     else if (command=="con")
  1885.     {
  1886.         //connect from user
  1887.         gApplication.sendPeerList(name);
  1888.         sendCurrentState(name);
  1889.         gApplication.addPeer(name);
  1890.     }
  1891.     else if (command=="aus")
  1892.     {
  1893.         //add user
  1894.         gApplication.addPeer(content);
  1895.     }
  1896.     else if (command=="rus")
  1897.     {
  1898.         //add user
  1899.         gApplication.removePeer(name);
  1900.     }
  1901.     else if (command=="loa")
  1902.     {
  1903.         loadData(content);
  1904.     }
  1905.     else if (command=="cpy")
  1906.     {
  1907.         var node=this.renderer.paste(content,true);
  1908.         //add listener to added child
  1909.         this.addNewShapeListeners(node);
  1910.         this.clipboard=this.renderer.copy(node);
  1911.         return node;
  1912.     }
  1913.     else if (command=="cmd")
  1914.     {
  1915.         var temp = content.split(" ");
  1916.         var oldID = null;
  1917.         if (this.selected)
  1918.             oldID=this.selected.id
  1919.         if (temp[2])
  1920.             this.selected = $(temp[2])
  1921.  
  1922.         if (temp[0]=="zoom")
  1923.         {
  1924.             this.externaleditCommand(temp[0], temp[1], true);
  1925.             $('_zoomValue').innerHTML=(c.getZoom()*100).toFixed(0)+"%";
  1926.         }
  1927.         else if (temp[0]=="fontFamily")
  1928.         {
  1929.             if (temp.length==5)
  1930.             {
  1931.                 this.selected = $(temp[4])
  1932.                 this.externaleditCommand(temp[0], temp[1] + " " + temp[2] + " " + temp[3], true);
  1933.             }
  1934.             else if (temp.length==4)
  1935.             {
  1936.                 this.selected = $(temp[3])
  1937.                 this.externaleditCommand(temp[0], temp[1] + " " + temp[2], true);
  1938.             }
  1939.             else
  1940.                 this.externaleditCommand(temp[0], temp[1], true);
  1941.         }
  1942.         else if (temp[0]=="fillcolor")
  1943.         {
  1944.             this.externaleditCommand(temp[0], temp[1], true);
  1945.         }
  1946.         else if (temp[0]=="linecolor")
  1947.         {
  1948.             this.externaleditCommand(temp[0], temp[1], true);
  1949.         }
  1950.         else if (temp[0]=="linewidth")
  1951.         {
  1952.             this.externaleditCommand(temp[0], temp[1], true);
  1953.         }
  1954.         else if (temp[0]=="linedashstyle")
  1955.         {
  1956.             this.externaleditCommand(temp[0], temp[1], true);
  1957.         }
  1958.         else if (temp[0]=="opacity")
  1959.         {
  1960.             this.externaleditCommand(temp[0], temp[1], true);
  1961.         }
  1962.         else if (temp[0]=="shadow")
  1963.         {
  1964.             this.externaleditCommand(temp[0], temp[1], true);
  1965.         }
  1966.         else if (temp[0]=="gradient")
  1967.         {
  1968.             this.externaleditCommand(temp[0], temp[1], true);
  1969.         }
  1970.         else if (temp[0]=="fontSize")
  1971.         {
  1972.             this.externaleditCommand(temp[0], temp[1], true);
  1973.         }
  1974.         else if (temp[0]=="fontColor")
  1975.         {
  1976.             this.externaleditCommand(temp[0], temp[1], true);
  1977.         }
  1978.         else if (temp[0]=="bold")
  1979.         {
  1980.             this.externaleditCommand(temp[0], temp[1], true);
  1981.         }
  1982.         else if (temp[0]=="italic")
  1983.         {
  1984.             this.externaleditCommand(temp[0], temp[1], true);
  1985.         }
  1986.         else if (temp[0]=="align")
  1987.         {
  1988.             this.externaleditCommand(temp[0], temp[1], true);
  1989.         }
  1990.         else if (temp[0]=="bringtofront")
  1991.         {
  1992.             this.bringToFront();
  1993.         }
  1994.         else if (temp[0]=="sendtoback")
  1995.         {
  1996.             this.sendToBack();
  1997.         }
  1998.         else if (temp[0]=="reset")
  1999.         {
  2000.             this.removeAll();
  2001.             this.setPageSize(this.DEFAULT_PAGE_WIDTH,this.DEFAULT_PAGE_HEIGHT);
  2002.         }
  2003.         else if (temp[0]=="deleteSelection")
  2004.         {
  2005.             this.deleteSelection();
  2006.         }
  2007.         else if (temp[0]=="txt")
  2008.         {
  2009.             var newtext = remoteData.substring(9+temp[1].length+temp[2].length);
  2010.             
  2011.             var shapeFont=this.renderer.getFont(this.selected);
  2012.             this.renderer.setShapeText(this.selected,newtext,this.font,false,shapeFont,this.zoom);
  2013.         }
  2014.         else if (temp[0]=="grid")
  2015.         {
  2016.             if(temp[0]=='on')
  2017.             {
  2018.                 $('_page').style.backgroundImage="url(images/grid.jpg)";
  2019.             }
  2020.             else{
  2021.                 $('_page').style.backgroundImage="";
  2022.             }
  2023.         }
  2024.  
  2025.         if (oldID)
  2026.             this.select($(oldID));
  2027.     }
  2028.     
  2029.     if (command=="mvs")
  2030.     {
  2031.         var oldID = null;
  2032.         if (this.selected)
  2033.             oldID=this.selected.id
  2034.         //moving a shape
  2035.         var temp = content.split(" ");
  2036.         this.selected = $(temp[0]);
  2037.         if (this.selected)
  2038.             this.updateShape(temp[1], temp[2], temp[3], temp[4], temp[5]);
  2039.         if (oldID)
  2040.             this.select($(oldID));
  2041.     }
  2042.     else if (command=="mvc")
  2043.     {
  2044.         //moving a connector
  2045.     }
  2046.     else if (command=="pgs")
  2047.     {
  2048.         //set page size
  2049.         var temp = content.split(" ");
  2050.         this.setPageSize(temp[0],temp[1]);
  2051.     }
  2052. }
  2053.  
  2054. function transmit(aUser, aApplication, aMessage)
  2055. {
  2056.     //loop through all users and transmit to them
  2057.     if (typeof(window.external)!="undefined" && typeof(window.external.transmit)!="undefined")
  2058.         window.external.transmit(aUser, aApplication, aMessage);
  2059. }
  2060.  
  2061. //Application handling
  2062. function Application()
  2063. {
  2064.     this.reset();
  2065. }
  2066.  
  2067. Application.prototype.reset=function()
  2068. {
  2069.     this.iPeers=new Array();
  2070.     this.iSource=false;
  2071.     this.iViewing="";
  2072. }
  2073.  
  2074. Application.prototype.broadcast=function(application, message)
  2075. {
  2076.     if (typeof(window.external)!="undefined" && typeof(window.external.broadcast)!="undefined")
  2077.         window.external.broadcast(application, message);
  2078. }
  2079.  
  2080. Application.prototype.transmit=function(application, message)
  2081. {
  2082.     //loop through all users and transmit to them
  2083.     for (var i=0; i < this.iPeers.length; i++)
  2084.     {
  2085.         if (typeof(window.external)!="undefined" && typeof(window.external.transmit)!="undefined")
  2086.             window.external.transmit(this.iPeers[i].iName, application, message);
  2087.     }
  2088. }
  2089.  
  2090. Application.prototype.sendPeerList=function(aName)
  2091. {
  2092.     for (var i=0; i < this.iPeers.length; i++)
  2093.     {
  2094.         if (typeof(window.external)!="undefined" && typeof(window.external.transmit)!="undefined")
  2095.             window.external.transmit(aName, "w", "aus " + this.iPeers[i].iName);
  2096.     }
  2097. }
  2098.  
  2099. Application.prototype.addPeer=function(aName)
  2100. {
  2101.     this.iPeers[this.iPeers.length] = new Peer(aName);
  2102.     insertParticipant(aName);
  2103. }
  2104.  
  2105. Application.prototype.checkPeerExist=function(aName)
  2106. {
  2107.     for (var i = 0; i < this.iPeers.length; i++)
  2108.     {
  2109.         if (this.iPeers[i].iName == aName)
  2110.             return true;
  2111.     }
  2112.     return false;
  2113. }
  2114.  
  2115. Application.prototype.removePeer=function(aName)
  2116. {
  2117.     removeParticipant(aName);
  2118.     for (var i = 0; i < this.iPeers.length; i++)
  2119.     if (this.iPeers[i].iName == aName)
  2120.     {
  2121.         this.iPeers.splice(i,1);
  2122.         return;
  2123.     }
  2124. }
  2125.  
  2126. function Peer(aName)
  2127. {
  2128.     this.iName=aName;
  2129. }
  2130.  
  2131. var gApplication;
  2132.  
  2133. //announce the drawing to the rest of the workspace.
  2134. function announce()
  2135. {
  2136.     if (gApplication.iSource)
  2137.     {
  2138.         gApplication.broadcast('w', "ann draw");
  2139.         if (iConnectionMode!="Private")
  2140.             setTimeout('announce()',60000);
  2141.     }
  2142.     else
  2143.     {
  2144.         gApplication.broadcast('w', "stp draw");
  2145.     }
  2146. }
  2147.  
  2148. function initDrawing()
  2149. {
  2150.     if (!gApplication.iSource)
  2151.     {
  2152.         stopDrawing();
  2153.         gApplication.iSource = true;
  2154.         announce();
  2155.     }
  2156.     Activate('w');
  2157.     hide("startdrawing");
  2158.     show("drawparticipant");
  2159. }
  2160.  
  2161. function stopDrawing()
  2162. {
  2163.     if (gApplication.iSource)
  2164.     {
  2165.         gApplication.reset();
  2166.         announce();
  2167.     }
  2168.     else
  2169.     {
  2170.         this.iViewing = "";
  2171.         gApplication.transmit('w', "rus ");
  2172.         gApplication.reset();
  2173.         var invitelist=document.getElementById("Particips");
  2174.         invitelist.innerHTML="";
  2175.     }    
  2176.     hide("drawparticipant");
  2177.     Activate('c');
  2178.     show("startdrawing");
  2179. }
  2180.  
  2181. function sendCurrentState(aName)
  2182. {
  2183. /*    Try.these(c.renderer.savePolyLinePaths());
  2184.     dummy=c.getRealData();
  2185.     transmit(aName, 'w', "loa " + dummy);
  2186. */
  2187.     var format=c.renderer.EXTENSION;
  2188.     var dummy=getAllData(format);
  2189.     var data=(dummy.innerHTML)?dummy.innerHTML:dummy.xml;
  2190.     transmit(aName, 'w', "loa " + data);
  2191. }
  2192.  
  2193. function loadData(content)
  2194. {
  2195.     if(content){
  2196.         var div=c.getValidDocumentFromResponse(content)
  2197.         c.open(div);
  2198.     }
  2199. }
  2200.  
  2201. function viewDrawing(aName)
  2202. {
  2203.     if (aName!=this.iViewing)
  2204.     {
  2205.         if (this.iViewing)
  2206.         {
  2207.             //we are viewing somebody, disconnect from them before connecting
  2208.         }
  2209.         this.iViewing=aName;
  2210.     
  2211.         if (!gApplication.checkPeerExist(aName))
  2212.         {
  2213.             gApplication.addPeer(aName);
  2214.             gApplication.iSource=false;
  2215.             gApplication.transmit('w', "con " + aName);
  2216.         }
  2217.         hide("startdrawing");
  2218.         show("drawparticipant");
  2219.     }
  2220.         Activate("w");
  2221. }
  2222.  
  2223. function insertInvitation(aUser, aMessage)
  2224. {
  2225.     var invitelist = document.getElementById("Invites");
  2226.     var existingItem = document.getElementById('invite' + aUser);
  2227.     if (!existingItem)
  2228.     {
  2229.         var listElement = document.createElement("li");
  2230.         listElement.setAttribute('id', 'invite' + aUser);
  2231.         var newlink = document.createElement('a');
  2232.         newlink.setAttribute('href', 'javascript:viewDrawing("' + aUser + '")');
  2233.         var text = document.createTextNode(aUser);
  2234.         newlink.appendChild(text);
  2235.         listElement.appendChild(newlink);
  2236.         invitelist.appendChild(listElement);
  2237.         if (typeof(window.external)!="undefined" && typeof(window.external.observe)!="undefined")
  2238.             window.external.observe(aUser);
  2239.             
  2240.         var chatElement = document.createElement("div");
  2241.         var newlink = document.createElement('a');
  2242.         newlink.setAttribute('href', 'javascript:viewDrawing("' + aUser + '")');
  2243.         var text = document.createTextNode("Click here");
  2244.         newlink.appendChild(text);
  2245.         var text2 = document.createTextNode(aUser + " started a shared whiteboard. ");
  2246.         var text3 = document.createTextNode(" to view or take part in the drawing. ");
  2247.         chatElement.appendChild(text2);
  2248.         chatElement.appendChild(newlink);
  2249.         chatElement.appendChild(text3);
  2250.  
  2251.         var chat = document.getElementById("c");
  2252.         chat.appendChild(chatElement);
  2253.     }
  2254. }
  2255.  
  2256. function removeInvitation(aUser)
  2257. {
  2258.     var invitelist = document.getElementById("Invites");
  2259.     var removeItem = document.getElementById('invite' + aUser);
  2260.     if (removeItem)
  2261.     {
  2262.         invitelist.removeChild(removeItem);
  2263.         if (typeof(window.external)!="undefined" && typeof(window.external.ignore)!="undefined")
  2264.             window.external.ignore(aUser);
  2265.     }
  2266. }
  2267.  
  2268. function insertParticipant(aUser, aMessage)
  2269. {
  2270.     var invitelist = document.getElementById("Particips");
  2271.     var existingItem = document.getElementById('participant' + aUser);
  2272.     if(!existingItem)
  2273.     {
  2274.         var listElement = document.createElement("li");
  2275.         listElement.setAttribute('id', 'participant' + aUser);
  2276.         var text = document.createTextNode(aUser);
  2277.         listElement.appendChild(text);
  2278.         invitelist.appendChild(listElement);
  2279.         if (typeof(window.external)!="undefined" && typeof(window.external.observe)!="undefined")
  2280.             window.external.observe(aUser);
  2281.     }
  2282. }
  2283.  
  2284. function removeParticipant(aUser)
  2285. {
  2286.     var invitelist = document.getElementById("Particips");
  2287.     var removeItem = document.getElementById('participant' + aUser);
  2288.     if (removeItem)
  2289.     {
  2290.         invitelist.removeChild(removeItem);
  2291.         if (typeof(window.external)!="undefined" && typeof(window.external.ignore)!="undefined")
  2292.             window.external.ignore(aUser);
  2293.     }
  2294. }
  2295.  
  2296. function userLeft(aUser)
  2297. {
  2298.     gApplication.removePeer(aUser);
  2299.     removeInvitation(aUser);
  2300. }
  2301.